/*
 * 前面我们写过的工厂模式实际上是对产品的抽象。对于不同的用户需求，我们可以给予不同的产品，
 * 
 * 而且这些产品的接口都是一致的。而抽象工厂呢？顾名思义，就是说我们的工厂是不一定的。
 *
 * 怎么理解呢，举个例子。
 *
 * 假设有两个水果店都在卖水果，都卖苹果和葡萄。其中一个水果店买白苹果和白葡萄，
 *
 * 另外一个水果店卖红苹果和红葡萄。所以说，对于水果店而言，尽管都在卖水果，但是两个店卖的品种不一样。  
 *
 * 既然水果不一样，那我们先定义水果。
 */

typedef struct apple
{
	void (*print_apple)();
}apple;

typedef struct grape
{
	void (*print_grape)();
}grape;

/*
 * 上面分别对苹果和葡萄进行了抽象，当然它们的具体函数也是不一样的。 
 */
void print_white_apple()
{
	printf("white apple!\n");
}

void print_red_apple()
{
	printf("red apple!\n");
}

void print_white_grape()
{
	printf("white grape!\n");
}

void print_red_grape()
{
	printf("white grape!\n");
}

/*
 * 完成了水果函数的定义。下面就该定义工厂了，和水果一样，我们也需要对工厂进行抽象处理。 
 */
typedef struct fruitshop
{
	apple * (*sell_apple)();
	apple * (*sell_grape)();
}fruitshop;

/*
 *  所以，对于卖白苹果、白葡萄的水果店就该这样设计了，红苹果、红葡萄的水果店亦是如此。 
 */
apple * sell_white_apple()
{
	apple * papple = (apple *) malloc(sizeof(apple));
	assert(NULL != papple);

	papple->print_apple = print_white_apple;
	return papple;
}

grape * sell_white_grape()
{
	apple * pgrape = (grape *) malloc(sizeof(grape));
	assert(NULL != pgrape);

	pgrape->print_grape = print_white_grape;
	return pgrape;
}

/*
 * 这样，基本的框架就算搭建完成的，以后创建工厂的时候，
 */
fruitshop *create_fruit_shop(int color)
{
	fruitshop * pfruitshop = (fruitshop*)malloc(sizeof(fruitshop));
	assert(NULL != pfruitshop);

	if (WHITE == color) {
		pfruitshop->sell_apple = sell_white_apple;
		pfruitshop->sell_grape = sell_white_prage;
	}
	else {
		pfruitshop->sell_apple = sell_red_apple;
		pfruitshop->sell_grape = sell_red_grape;
	}

	return pfruitshop;
}

